import React, { Component, ReactNode } from 'react';
import ErrorFallback from './ErrorFallback';
import type { MicroAppErrorBoundaryProps, ErrorFallbackProps } from '../../types';

interface State {
  hasError: boolean;
  error: Error | null;
  errorInfo: React.ErrorInfo | null;
  retryCount: number;
}

/**
 * 微应用错误边界组件
 * 
 * 功能特性：
 * - 捕获微应用运行时错误
 * - 提供友好的错误UI
 * - 支持自动恢复机制
 * - 提供手动刷新功能
 * - 集成Toast提示
 * - 支持重试计数和延迟
 */
class MicroAppErrorBoundary extends Component<MicroAppErrorBoundaryProps, State> {
  private retryTimer: NodeJS.Timeout | null = null;

  constructor(props: MicroAppErrorBoundaryProps) {
    super(props);
    
    this.state = {
      hasError: false,
      error: null,
      errorInfo: null,
      retryCount: 0,
    };
  }

  static getDerivedStateFromError(error: Error): Partial<State> {
    // 更新 state 使下一次渲染能够显示降级后的 UI
    return {
      hasError: true,
      error,
    };
  }

  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
    console.error('微应用错误边界捕获到错误:', error, errorInfo);
    
    this.setState({
      error,
      errorInfo,
    });

    // 调用错误回调
    if (this.props.onError) {
      this.props.onError(error, errorInfo);
    }

    // 显示Toast提示
    if (this.props.showToast) {
      this.showToast(this.props.toastMessage || '应用加载失败，请重试');
    }

    // 自动重试逻辑
    if (this.props.autoRetry && this.state.retryCount < (this.props.retryCount || 3)) {
      this.scheduleRetry();
    }
  }

  componentWillUnmount() {
    // 清理定时器
    if (this.retryTimer) {
      clearTimeout(this.retryTimer);
      this.retryTimer = null;
    }
  }

  /**
   * 显示Toast提示
   */
  private showToast = (message: string) => {
    // 创建Toast元素
    const toast = document.createElement('div');
    toast.style.cssText = `
      position: fixed;
      top: 20px;
      left: 50%;
      transform: translateX(-50%);
      background-color: #ff4d4f;
      color: white;
      padding: 12px 24px;
      border-radius: 6px;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
      z-index: 10000;
      font-size: 14px;
      font-weight: 500;
      animation: sei-toast-fade-in 0.3s ease-out;
    `;
    toast.textContent = message;

    // 添加CSS动画
    if (!document.getElementById('sei-toast-styles')) {
      const style = document.createElement('style');
      style.id = 'sei-toast-styles';
      style.textContent = `
        @keyframes sei-toast-fade-in {
          from {
            opacity: 0;
            transform: translateX(-50%) translateY(-10px);
          }
          to {
            opacity: 1;
            transform: translateX(-50%) translateY(0);
          }
        }
        @keyframes sei-toast-fade-out {
          from {
            opacity: 1;
            transform: translateX(-50%) translateY(0);
          }
          to {
            opacity: 0;
            transform: translateX(-50%) translateY(-10px);
          }
        }
      `;
      document.head.appendChild(style);
    }

    document.body.appendChild(toast);

    // 3秒后移除Toast
    setTimeout(() => {
      if (toast.parentNode) {
        toast.style.animation = 'sei-toast-fade-out 0.3s ease-out forwards';
        setTimeout(() => {
          if (toast.parentNode) {
            document.body.removeChild(toast);
          }
        }, 300);
      }
    }, 3000);
  };

  /**
   * 安排重试
   */
  private scheduleRetry = () => {
    const delay = this.props.retryDelay || 1000;
    
    this.retryTimer = setTimeout(() => {
      this.retry();
    }, delay);
  };

  /**
   * 重试方法
   */
  private retry = () => {
    console.log('重试微应用加载...');
    
    this.setState(prevState => ({
      hasError: false,
      error: null,
      errorInfo: null,
      retryCount: prevState.retryCount + 1,
    }));

    // 调用重试回调
    if (this.props.onRetry) {
      this.props.onRetry();
    }
  };

  /**
   * 重置错误状态
   */
  private resetError = () => {
    console.log('重置错误状态...');
    
    this.setState({
      hasError: false,
      error: null,
      errorInfo: null,
      retryCount: 0,
    });

    // 清理定时器
    if (this.retryTimer) {
      clearTimeout(this.retryTimer);
      this.retryTimer = null;
    }
  };

  render(): ReactNode {
    if (this.state.hasError && this.state.error) {
      // 使用自定义错误组件或默认错误组件
      const FallbackComponent = this.props.fallback || ErrorFallback;
      
      const fallbackProps: ErrorFallbackProps = {
        error: this.state.error,
        resetError: this.resetError,
        retry: this.retry,
      };

      return <FallbackComponent {...fallbackProps} />;
    }

    return this.props.children;
  }
}

export default MicroAppErrorBoundary;